using Microsoft.EntityFrameworkCore;
using UniversalAdmin.Application.DTOs;
using UniversalAdmin.Domain.Entities;
using UniversalAdmin.Infrastructure.Data.Contexts;

namespace UniversalAdmin.Application.Services;

public class RolePermissionService : IRolePermissionService
{
    private readonly ApplicationDbContext _context;

    public RolePermissionService(ApplicationDbContext context)
    {
        _context = context;
    }

    // 为角色分配权限
    public async Task AssignPermissionsToRoleAsync(Guid roleId, List<Guid> permissionIds)
    {
        // 验证角色是否存在
        var role = await _context.Roles
            .Include(r => r.RolePermissions)
            .FirstOrDefaultAsync(r => r.Id == roleId);

        if (role == null)
        {
            throw new KeyNotFoundException($"角色ID {roleId} 不存在");
        }

        // 验证权限是否存在
        if (permissionIds != null && permissionIds.Any())
        {
            var validPermissionIds = await _context.Permissions
                .Where(p => permissionIds.Contains(p.Id))
                .Select(p => p.Id)
                .ToListAsync();

            if (validPermissionIds.Count != permissionIds.Count)
            {
                throw new KeyNotFoundException("部分权限ID不存在");
            }
        }

        // 清除现有权限
        var existingRolePermissions = role.RolePermissions.ToList();
        _context.RolePermissions.RemoveRange(existingRolePermissions);

        // 添加新权限
        if (permissionIds != null && permissionIds.Any())
        {
            var newRolePermissions = permissionIds.Select(permissionId => new RolePermission
            {
                RoleId = roleId,
                PermissionId = permissionId
            });

            await _context.RolePermissions.AddRangeAsync(newRolePermissions);
        }

        await _context.SaveChangesAsync();
    }

    // 清空角色权限
    public async Task ClearRolePermissionsAsync(Guid roleId)
    {
        var rolePermissions = await _context.RolePermissions
            .Where(rp => rp.RoleId == roleId)
            .ToListAsync();

        _context.RolePermissions.RemoveRange(rolePermissions);
        await _context.SaveChangesAsync();
    }

    // 获取角色的权限列表
    public async Task<IEnumerable<PermissionDto>> GetRolePermissionsAsync(Guid roleId)
    {
        var permissions = await _context.RolePermissions
            .Where(rp => rp.RoleId == roleId)
            .Include(rp => rp.Permission)
            .Select(rp => rp.Permission)
            .Where(p => p != null)
            .ToListAsync();

        return permissions.Select(p => new PermissionDto(
            p!.Id,
            p!.Name,
            p!.Description,
            p!.Resource,
            p!.Action,
            p!.Type,
            p!.SortOrder,
            p!.IsEnabled
        ));
    }

    // 检查角色是否有指定权限
    public async Task<bool> HasPermissionAsync(Guid roleId, string resource, string action)
    {
        return await _context.RolePermissions
            .AnyAsync(rp => rp.RoleId == roleId &&
                           rp.Permission != null &&
                           rp.Permission.Resource == resource &&
                           rp.Permission.Action == action &&
                           rp.Permission.IsEnabled);
    }

    // 获取用户的所有权限
    public async Task<IEnumerable<PermissionDto>> GetUserPermissionsAsync(Guid userId)
    {
        var permissions = await _context.Users
            .Where(u => u.Id == userId)
            .SelectMany(u => u.Roles)
            .SelectMany(r => r.RolePermissions)
            .Select(rp => rp.Permission)
            .Where(p => p != null && p.IsEnabled)
            .Distinct()
            .ToListAsync();

        return permissions.Select(p => new PermissionDto(
            p!.Id,
            p!.Name,
            p!.Description,
            p!.Resource,
            p!.Action,
            p!.Type,
            p!.SortOrder,
            p!.IsEnabled
        ));
    }

    // 检查用户是否有指定权限
    public async Task<bool> UserHasPermissionAsync(Guid userId, string resource, string action)
    {
        return await _context.Users
            .Where(u => u.Id == userId)
            .SelectMany(u => u.Roles)
            .SelectMany(r => r.RolePermissions)
            .AnyAsync(rp => rp.Permission != null &&
                           rp.Permission.Resource == resource &&
                           rp.Permission.Action == action &&
                           rp.Permission.IsEnabled);
    }

    // 兼容旧版本的方法
    public async Task AssignRolePermissionAsync(RolePermissionDto dto)
    {
        // 验证角色是否存在
        var role = await _context.Roles
            .Include(r => r.MenuRoles)
            .FirstOrDefaultAsync(r => r.Id == dto.RoleId);

        if (role == null)
        {
            throw new KeyNotFoundException($"角色ID {dto.RoleId} 不存在");
        }

        // 检查 MenuIds
        if (dto.MenuIds == null || !dto.MenuIds.Any())
        {
            throw new ArgumentException("MenuIds 不能为空");
        }

        // 去重处理
        var uniqueMenuIds = dto.MenuIds.Distinct().ToList();

        // 一次性查询所有有效的菜单ID
        var validMenuIds = await _context.Menus
            .Where(m => uniqueMenuIds.Contains(m.Id))
            .Select(m => m.Id)
            .ToListAsync();

        if (!validMenuIds.Any())
        {
            throw new KeyNotFoundException("没有找到有效的菜单ID");
        }

        // 获取当前角色的所有菜单ID
        var currentMenuIds = role.MenuRoles.Select(mr => mr.MenuId).ToList();

        // 需要添加的菜单ID
        var menuIdsToAdd = validMenuIds.Except(currentMenuIds).ToList();

        // 需要移除的菜单ID
        var menuIdsToRemove = currentMenuIds.Except(validMenuIds).ToList();

        // 添加新的菜单角色关系
        foreach (var menuId in menuIdsToAdd)
        {
            role.MenuRoles.Add(new MenuRole
            {
                MenuId = menuId,
                RoleId = dto.RoleId
            });
        }

        // 移除不再需要的菜单角色关系
        var menuRolesToRemove = role.MenuRoles
            .Where(mr => menuIdsToRemove.Contains(mr.MenuId))
            .ToList();

        _context.MenuRoles.RemoveRange(menuRolesToRemove);

        // 保存更改
        await _context.SaveChangesAsync();
    }

    public async Task<List<Guid>> GetMenuIdsByRoleAsync(Guid roleId)
    {
        return await _context.MenuRoles
            .Where(rm => rm.RoleId == roleId)
            .Select(rm => rm.MenuId)
            .ToListAsync();
    }
}